﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.Routing;

using ProjectBase.Core;
using ProjectBase.Core.Web;
using System.Linq.Expressions;

namespace ProjectBase.Mvc
{
    public class AsyncListView : VisualControl<IViewModel>
    {
        #region members
        string _jsonAction;
        RouteValueDictionary _jsonRouteValues;
        string _jsonUrl;
        string _noResultText = "NoResult";
        #endregion

        #region Render
        protected override void BuildControls()
        {
            base.BuildControls();
            Controls.Add(CreateListView());
        }
        #endregion Render

        #region Create
        protected virtual PlaceHolder CreateListView()
        {
            var showAddItem = !Model.IsActionDetail() && AddedItemsCollectionName.IsNotEmpty();

            return new PlaceHolder
            {
                showAddItem ? CreateAddItemButton() : null,
                new Div("asyncList")
                    .SetAttribute("data-jsonurl", JsonUrl),
                new Div()
                    .SetAttribute(Attr.Style, "display: none;")
                    .AddControls
                    (
                        //showAddItem ?  CreateOldMembersParagraph() : null,
                        CreateTable(),
                        new Paragraph("{NoResult}")
                        {
                            new Literal(NoResultText)
                        },
                        showAddItem ?  CreateNewMembersParagraph() : null,
                        showAddItem ?  CreateNewMembersTable() : null
                    )
            };
        }
        protected virtual Div CreateAddItemButton()
        {
            return new Div("filterer")
            {
                new Button("...", doLocalize: true)
                    .SetCssClassName("async")
                    .SetName("addNewItems")
                    .SetAttribute("data-asyncurl", Url.Action(Constants.Actions.List, ItemControllerName))
                    .SetAttribute("data-nameforaddeditem", AddedItemsCollectionName),
                //.SetAttribute("data-removedname", RemovedItemsCollectionName),,
            };
        }

        protected virtual Table CreateTable()
        {
            return new Table("list")
                .SetAttribute("data-removeditemname", RemovedItemsCollectionName)
                .AddControls
                (
                    CreateCaption(),
                    CreateHead(),
                    CreateBody()
                );
        }

        #region new items Template
        protected virtual Paragraph CreateNewMembersParagraph()
        {
            return new Paragraph("newMembers")
            {
                new Literal("NewRelatedEntities", true)
            };
        }

        protected virtual Table CreateNewMembersTable()
        {
            var body = new TableBody();

            return new Table("list newMembers")
            {
                new TableHead
                {
                    new TableRow
                    {
                        new TableHeaderCell {new Literal(GetLocalized(Constants.Common.ID))},
                        new TableHeaderCell {new Literal(GetLocalized(Constants.Common.Description))},
                    }
                },
                body
            };
        }

        protected virtual Paragraph CreateOldMembersParagraph()
        {
            return new Paragraph("oldMembers")
            {
                new Literal("ExistingRelatedEntities", true)
            };
        }
        #endregion new items Template

        #region caption
        protected virtual Caption CreateCaption()
        {
            return new Caption("{Caption}")
            {
                new Span
                {
                    CreateFirstPageLink(),
                    CreatePreviousPageLink(),
                    CreateCurrentPageText(),
                    CreateNextPageLink(),
                    CreateLastPageLink()
                }
            };
        }

        protected virtual IVisualControl CreateFirstPageLink()
        {
            return new Anchor("paging") { new Literal("\u2502\u25C4\u25C4") }
                .SetHref("{First}")
                .SetTitle("First")
                .AddCssClassName("{FirstDisabled}")
                ;
        }

        protected virtual IVisualControl CreatePreviousPageLink()
        {
            return new Anchor("paging") { new Literal("\u25C4") }
                .SetHref("{Previous}")
                .SetTitle("Previous")
                .AddCssClassName("{FirstDisabled}")
                ;
        }

        protected virtual Span CreateCurrentPageText()
        {
            return new Span()
                .SetTitle("TotalRowCount ({RowCount})")
                .AddControls
                (
                    new Literal("{CurrentPage} / {PageCount}"),
                    new Italic
                    {
                        new Literal(" ({RowCount})")
                    }
                );
        }

        protected virtual IVisualControl CreateNextPageLink()
        {
            return new Anchor("paging") { new Literal("\u25BA") }
                .SetHref("{Next}")
                .SetTitle("Next")
                .AddCssClassName("{LastDisabled}")
                ;
        }

        protected virtual IVisualControl CreateLastPageLink()
        {
            return new Anchor("paging") { new Literal("\u25BA\u25BA\u2502") }
                .SetHref("{Last}")
                .SetTitle("Last")
                .AddCssClassName("{LastDisabled}")
                ;
        }
        #endregion caption

        #region head
        protected virtual TableHead CreateHead()
        {
            return new TableHead("{Head}")
            {
                new TableRow
                {
                    CreateHeaderCellUpd(),
                    CreateHeaderCell(),
                    CreateHeaderCellDel(),
                    CreateHeaderCellRem(),
                }
            };
        }

        protected virtual TableHeaderCell CreateHeaderCellUpd()
        {
            return new TableHeaderCell("{Upd}")
            {
                new Span("{Align}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }

        protected virtual TableHeaderCell CreateHeaderCell()
        {
            return new TableHeaderCell("{Cell}")
            {
                new Anchor("{Align}")
                    .SetHref("{Url}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }

        protected virtual TableHeaderCell CreateHeaderCellDel()
        {
            return new TableHeaderCell("{Del}")
            {
                new Span("center {Align}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }

        protected virtual TableHeaderCell CreateHeaderCellRem()
        {
            return new TableHeaderCell("{Rem}")
            {
                new Span("center {Align}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }
        #endregion head

        #region body
        protected virtual TableBody CreateBody()
        {
            return new TableBody
            {
                new TableRow("{Row}")
                {
                    CreateTableCellUpd(),
                    CreateTableCell(),
                    CreateTableCellDel(),
                    CreateTableCellRem()
                }
            };
        }

        protected virtual TableCell CreateTableCellUpd()
        {
            return new TableCell("{Upd}")
            {
                new Anchor("{Align}")
                    .SetHref("{Url}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }

        protected virtual TableCell CreateTableCell()
        {
            return new TableCell("{Cell}")
            {
                new Anchor("{Align}")
                    .SetHref("{Url}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }

        protected virtual TableCell CreateTableCellDel()
        {
            return new TableCell("{Del}")
            {
                new Anchor("center redC {Align}")
                    .SetHref("{Url}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("{Txt}")
                    )
            };
        }

        protected virtual TableCell CreateTableCellRem()
        {
            return new TableCell("{Rem}")
            {
                new Input(InputType.Hidden)
                    .SetValue("{ID}"),
                new Anchor("center redC doRemove {Align}")
                    .SetHref("{Url}")
                    .SetTitle("{Tip}")
                    .AddControls
                    (
                        new Literal("X")
                    ),
                new Input(InputType.Hidden)
                    .SetValue("{Txt}")
            };
        }
        #endregion

        #endregion Create

        #region properties
        public virtual string JsonUrl
        {
            get
            {
                if (_jsonUrl.IsEmpty())
                {
                    var showRemove = !Model.IsActionDetail() && RemovedItemsCollectionName.IsNotEmpty();
                    if (showRemove)
                    {
                        AddJsonRouteValue("showRemoveAction", "true");
                    }
                    return Url.Action(JsonAction, JsonController, JsonRouteValues);
                }
                return _jsonUrl;
            }
            set { _jsonUrl = value; }
        }

        public virtual string JsonAction
        {
            get
            {
                if (_jsonAction.IsEmpty())
                {
                    return Constants.Actions.Special.AsyncList;
                }
                return _jsonAction;
            }
            set { _jsonAction = value; }
        }

        public virtual string JsonController { get; set; }

        public virtual RouteValueDictionary JsonRouteValues
        {
            get
            {
                if (_jsonRouteValues.IsNull())
                {
                    _jsonRouteValues = new RouteValueDictionary();
                }
                return _jsonRouteValues;
            }
            set { _jsonRouteValues = value; }
        }

        public virtual string NoResultText
        {
            get
            {
                return NoResultLocalizedText.IsNotEmpty()
                           ? NoResultLocalizedText
                           : GetLocalized(_noResultText);
            }
            set { _noResultText = value; }
        }

        public virtual string NoResultLocalizedText { get; set; }

        public virtual string ItemControllerName { get; set; }

        public virtual string AddedItemsCollectionName { get; set; }

        public virtual string RemovedItemsCollectionName { get; set; }
        #endregion

        #region set
        /// <summary>
        ///     Optional! Used only when JsonUrl.IsEmpty().
        /// </summary>
        /// <param name = "controller"></param>
        /// <returns></returns>
        public virtual AsyncListView SetJsonController(string controller)
        {
            JsonController = controller;
            return this;
        }

        /// <summary>
        ///     Optional! Used only when JsonUrl.IsEmpty().
        ///     Default value Constants.Actions.AsyncList.
        /// </summary>
        /// <param name = "action"></param>
        /// <returns></returns>
        public virtual AsyncListView SetJsonAction(string action)
        {
            JsonAction = action;
            return this;
        }

        public virtual AsyncListView AddJsonRouteValue(string key, object value)
        {
            if (key.Is()
                && value.Is())
            {
                JsonRouteValues[key] = value;
            }
            return this;
        }

        public virtual AsyncListView AddJsonRouteValues(RouteValueDictionary routeValues)
        {
            foreach (var pair in routeValues)
            {
                AddJsonRouteValue(pair.Key, pair.Value);
            }
            return this;
        }

        public virtual AsyncListView SetNoResultText(string text)
        {
            NoResultText = text;
            return this;
        }

        public virtual AsyncListView SetAddedItemsCollection<TResult>(Expression<Func<IEnumerable<TResult>>> resultTarget)
            where TResult : class, IPersistentObject
        {
            if (resultTarget.Body.NodeType
                != ExpressionType.MemberAccess)
            {
                throw new NotSupportedException(
                    "Provided 'Expression<Func<IEnumerable<IPersistentObject>> resultTarget' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }
            var body = resultTarget.Body as MemberExpression;

            AddedItemsCollectionName = body.Member.Name;
            ItemControllerName = ItemControllerName ?? typeof(TResult).Name;
            JsonController = JsonController ?? ItemControllerName;

            //ResultTarget = resultTarget.Compile().Invoke();
            return this;
        }
        public virtual AsyncListView SetRemovedItemsCollection<TResult>(Expression<Func<IEnumerable<TResult>>> resultTarget)
            where TResult : class, IPersistentObject
        {
            if (resultTarget.Body.NodeType
                != ExpressionType.MemberAccess)
            {
                throw new NotSupportedException(
                    "Provided 'Expression<Func<IEnumerable<IPersistentObject>> resultTarget' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }
            var body = resultTarget.Body as MemberExpression;

            RemovedItemsCollectionName = body.Member.Name;
            ItemControllerName = ItemControllerName ?? typeof(TResult).Name;
            JsonController = JsonController ?? ItemControllerName;

            return this;
        }
        #endregion
    }
}